﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MiniCPU.Events;

namespace MiniCPU.Entities
{
    /// <summary>
    /// Register entity.
    /// </summary>
    public class Register : DataHolder
    {
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="Register"/> class.
        /// </summary>
        /// <param name="numberOfBits">The number of bits.</param>
        /// <param name="name">The name of teh register.</param>
        public Register(int numberOfBits, string name)
            : base(name, 0, numberOfBits)
        {
            this.Increment = new ControlPort(name + ":Increment");
            this.Clear = new ControlPort(name + ":Clear");
            this.Load = new ControlPort(name + ":Load");
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the increment control port.
        /// </summary>
        /// <value>The increment control port.</value>
        public ControlPort Increment { get; set; }

        /// <summary>
        /// Gets or sets the clear control port.
        /// </summary>
        /// <value>The clear control port.</value>
        public ControlPort Clear { get; set; }

        /// <summary>
        /// Gets or sets the load control port.
        /// </summary>
        /// <value>The load control port.</value>
        public ControlPort Load { get; set; }

        /// <summary>
        /// Gets or sets the data on load control port.
        /// </summary>
        /// <value>The data on load control port.</value>
        public LimitedData DataOnLoad { get; set; }
        #endregion

        #region Methods
        /// <summary>
        /// Clock ticked event handler.
        /// </summary>
        protected override void Clock_ClockTicked()
        {
            base.Clock_ClockTicked();
            if (this.Clear.Value)
            {
                UpdateValue(0);
            }
            else if (this.Load.Value)
            {
                if (this.DataOnLoad.NumberOfBits > this.NumberOfBits)
                {
                    UpdateValue(this.DataOnLoad.GetPartOfData(NumberOfBits - 1, 0).IntValue);
                }
                else
                {
                    UpdateValue(this.DataOnLoad.IntValue);
                }
            }
            else if (this.Increment.Value)
            {
                if (this.IntValue + 1 > Math.Pow(2, this.NumberOfBits) - 1)
                {
                    UpdateValue(0);
                }
                else
                {
                    UpdateValue(IntValue + 1);
                }
            }
        }
        #endregion
    }
}
